﻿namespace Iesi.Collections.Generic
{
    using Iesi.Collections;
    using System;
    using System.Collections;
    using System.Collections.Generic;

    [Serializable]
    public abstract class Set<T> : ISet<T>, ICollection<T>, IEnumerable<T>, ISet, ICollection, IEnumerable, ICloneable
    {
        protected Set()
        {
        }

        public abstract bool Add(T o);
        public abstract bool AddAll(ICollection<T> c);
        public abstract void Clear();
        public virtual object Clone()
        {
            Set<T> set = (Set<T>) Activator.CreateInstance(base.GetType());
            set.AddAll(this);
            return set;
        }

        public abstract bool Contains(T o);
        public abstract bool ContainsAll(ICollection<T> c);
        public abstract void CopyTo(T[] array, int index);
        public virtual ISet<T> ExclusiveOr(ISet<T> a)
        {
            ISet<T> set = (ISet<T>) this.Clone();
            foreach (T local in a)
            {
                if (set.Contains(local))
                {
                    set.Remove(local);
                }
                else
                {
                    set.Add(local);
                }
            }
            return set;
        }

        public static ISet<T> ExclusiveOr(ISet<T> a, ISet<T> b)
        {
            if ((a == null) && (b == null))
            {
                return null;
            }
            if (a == null)
            {
                return (ISet<T>) b.Clone();
            }
            if (b == null)
            {
                return (ISet<T>) a.Clone();
            }
            return a.ExclusiveOr(b);
        }

        public abstract IEnumerator<T> GetEnumerator();
        bool ISet.Add(object o)
        {
            return this.Add((T) o);
        }

        bool ISet.AddAll(ICollection c)
        {
            bool flag = false;
            foreach (T local in c)
            {
                flag |= this.Add(local);
            }
            return flag;
        }

        bool ISet.Contains(object o)
        {
            return ((o is T) && this.Contains((T) o));
        }

        bool ISet.ContainsAll(ICollection c)
        {
            ICollection<T> is2 = new List<T>(c.Count);
            foreach (object obj2 in c)
            {
                if (obj2 is T)
                {
                    is2.Add((T) obj2);
                }
                else
                {
                    return false;
                }
            }
            return this.ContainsAll(is2);
        }

        ISet ISet.ExclusiveOr(ISet a)
        {
            return this.NonGenericExclusiveOr(a);
        }

        ISet ISet.Intersect(ISet a)
        {
            return this.NonGenericIntersect(a);
        }

        ISet ISet.Minus(ISet a)
        {
            return this.NonGenericMinus(a);
        }

        bool ISet.Remove(object o)
        {
            return ((o is T) && this.Remove((T) o));
        }

        bool ISet.RemoveAll(ICollection c)
        {
            ICollection<T> is2 = new List<T>(c.Count);
            foreach (object obj2 in c)
            {
                if (obj2 is T)
                {
                    is2.Add((T) obj2);
                }
            }
            return this.RemoveAll(is2);
        }

        bool ISet.RetainAll(ICollection c)
        {
            ICollection<T> is2 = new List<T>(c.Count);
            foreach (object obj2 in c)
            {
                if (obj2 is T)
                {
                    is2.Add((T) obj2);
                }
            }
            return this.RetainAll(is2);
        }

        ISet ISet.Union(ISet a)
        {
            return this.NonGenericUnion(a);
        }

        public virtual ISet<T> Intersect(ISet<T> a)
        {
            ISet<T> set = (ISet<T>) this.Clone();
            if (a != null)
            {
                set.RetainAll(a);
                return set;
            }
            set.Clear();
            return set;
        }

        public static ISet<T> Intersect(ISet<T> a, ISet<T> b)
        {
            if ((a == null) && (b == null))
            {
                return null;
            }
            if (a == null)
            {
                return b.Intersect(a);
            }
            return a.Intersect(b);
        }

        public virtual ISet<T> Minus(ISet<T> a)
        {
            ISet<T> set = (ISet<T>) this.Clone();
            if (a != null)
            {
                set.RemoveAll(a);
            }
            return set;
        }

        public static ISet<T> Minus(ISet<T> a, ISet<T> b)
        {
            if (a == null)
            {
                return null;
            }
            return a.Minus(b);
        }

        protected abstract void NonGenericCopyTo(Array array, int index);
        protected virtual ISet NonGenericExclusiveOr(ISet a)
        {
            ISet set = (ISet) this.Clone();
            foreach (object obj2 in a)
            {
                if (set.Contains(obj2))
                {
                    set.Remove(obj2);
                }
                else
                {
                    set.Add(obj2);
                }
            }
            return set;
        }

        protected virtual ISet NonGenericIntersect(ISet a)
        {
            ISet set = (ISet) this.Clone();
            if (a != null)
            {
                set.RetainAll(a);
                return set;
            }
            set.Clear();
            return set;
        }

        protected virtual ISet NonGenericMinus(ISet a)
        {
            ISet set = (ISet) this.Clone();
            if (a != null)
            {
                set.RemoveAll(a);
            }
            return set;
        }

        protected virtual ISet NonGenericUnion(ISet a)
        {
            ISet set = (ISet) this.Clone();
            if (a != null)
            {
                set.AddAll(a);
            }
            return set;
        }

        public static Set<T> operator &(Set<T> a, Set<T> b)
        {
            return (Set<T>) Set<T>.Intersect(a, b);
        }

        public static Set<T> operator |(Set<T> a, Set<T> b)
        {
            return (Set<T>) Set<T>.Union(a, b);
        }

        public static Set<T> operator ^(Set<T> a, Set<T> b)
        {
            return (Set<T>) Set<T>.ExclusiveOr(a, b);
        }

        public static Set<T> operator -(Set<T> a, Set<T> b)
        {
            return (Set<T>) Set<T>.Minus(a, b);
        }

        public abstract bool Remove(T o);
        public abstract bool RemoveAll(ICollection<T> c);
        public abstract bool RetainAll(ICollection<T> c);
        void ICollection<T>.Add(T item)
        {
            this.Add(item);
        }

        void ICollection.CopyTo(Array array, int index)
        {
            this.NonGenericCopyTo(array, index);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        public virtual ISet<T> Union(ISet<T> a)
        {
            ISet<T> set = (ISet<T>) this.Clone();
            if (a != null)
            {
                set.AddAll(a);
            }
            return set;
        }

        public static ISet<T> Union(ISet<T> a, ISet<T> b)
        {
            if ((a == null) && (b == null))
            {
                return null;
            }
            if (a == null)
            {
                return (ISet<T>) b.Clone();
            }
            if (b == null)
            {
                return (ISet<T>) a.Clone();
            }
            return a.Union(b);
        }

        public abstract int Count { get; }

        public abstract bool IsEmpty { get; }

        public virtual bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        public abstract bool IsSynchronized { get; }

        public abstract object SyncRoot { get; }
    }
}

